package com.haoma.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.haoma.dto.LikeDto;
import com.haoma.entity.*;
import com.haoma.exception.BlogException;
import com.haoma.mapper.*;
import com.haoma.minio.MinIOConfig;
import com.haoma.minio.MinIOConfigProperties;
import com.haoma.service.TalkService;
import com.haoma.vo.AllTalkVo;
import com.haoma.vo.CommentVo;
import com.haoma.vo.TalkVo;
import io.minio.BucketExistsArgs;
import io.minio.MakeBucketArgs;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import java.util.*;
import java.util.stream.Collectors;

/**
 * Description:
 */
@Service
public class TalkServiceImpl extends ServiceImpl<TalkMapper, Talk> implements TalkService {


    @Autowired
    private TalkMapper talkMapper;

    @Autowired
    private TalkUserMapper talkUserMapper;

    @Autowired
    private MinIOConfigProperties minIOConfigProperties;

    @Autowired
    private MinIOConfig minIOConfig;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private TalkCommentMapper talkCommentMapper;

    @Autowired
    private UserCommentRelationMapper userCommentRelationMapper;

    @Autowired
    private TalkCommentRelationMapper talkCommentRelationMapper;


    /**
     * 获取所有的说说
     *
     * @return
     */
    public List<AllTalkVo> getTalkList() {
        // 查询全部的数据
        List<TalkVo> talkVoList = talkMapper.getTalkList();

        // 将说说的信息提取出来
        Set<Talk> talkSet = talkVoList.stream()
                .map(talkVo -> {
                    // 封装说说的基本信息
                    Talk talk = new Talk();
                    talk.setCommentCount(talkVo.getCommentCount());
                    talk.setContent(talkVo.getContent());
                    talk.setLikeCount(talkVo.getLikeCount());
                    talk.setCreateTime(talkVo.getTCreateTime());
                    talk.setId(talkVo.getId());
                    return talk;
                }).collect(Collectors.toSet());

        // 封装返回数据
        List<AllTalkVo> allTalkVoList = new ArrayList<>();

        // 获取所有的用户
        List<TalkUser> talkUserList = talkUserMapper
                .selectList(new LambdaQueryWrapper<TalkUser>()
                        .orderByDesc(TalkUser::getCreateTime));

        // 遍历说说
        for (Talk talk : talkSet) {
            // 封装所有的评论
            Set<CommentVo> commentVoSet = new HashSet<>();
            // 存储返回数据
            AllTalkVo allTalkVo = new AllTalkVo();
            // 将基本信息存储
            allTalkVo.setTalk(talk);
            // 存储图片数据
            Set<String> stringList = new HashSet<>();
            // 存储当前数据
            List<LikeDto> likeDtoList = new ArrayList<>();
            // 处理图片用的
            Map<Integer, Set<String>> map = new HashMap<>();
            // 遍历用户
            for (TalkUser talkUser : talkUserList) {
                // 从redis中查询
                Object o = redisTemplate.opsForHash().get("talk" + talk.getId(), talkUser.getId());
                if (o == null) {
                    break;
                }
                LikeDto bean = JSONUtil.toBean(o.toString(), LikeDto.class);
                if (bean.getUrl().equals(talkUser.getAvatar()) && bean.getIsLiked()) {
                    // 有就存储
                    likeDtoList.add(bean);
                }
            }
            // 遍历全部的数据
            for (TalkVo talkVo : talkVoList) {
                // 判断
                if (talk.getId() == talkVo.getId()) {
                    if (talkVo.getIsDeleted() != null) {
                        if (talkVo.getIsDeleted() == 0) {
                            // 封装评论数据
                            CommentVo commentVo = new CommentVo();
                            commentVo.setComment(talkVo.getComment());
                            commentVo.setTcCreateTime(talkVo.getTcCreateTime());
                            commentVo.setUserUrl(talkVo.getUserUrl());
                            commentVo.setName(talkVo.getName());
                            commentVoSet.add(commentVo);
                        }
                    }
                    // 存储图片路径
                    stringList.add(talkVo.getUrl());
                    // 去重
                    map.put(talkVo.getId(), stringList);
                }
            }
            // 存储所有的评论
            List<CommentVo> commentVos = new ArrayList<>();
            if (!CollectionUtils.isEmpty(commentVoSet)) {
                commentVos = new ArrayList<>(commentVoSet);
                // 排序
                commentVos = commentVos.stream().sorted(Comparator.comparing(CommentVo::getTcCreateTime)).toList();
                // 存评论
                allTalkVo.setCommentList(commentVos);
            }
            // 获取到图片路径
            Set<String> setUrlList = map.entrySet().iterator().next().getValue();
            // 存储图片
            allTalkVo.setUrlList(setUrlList);
            // 存储图片路径
            allTalkVo.setTalkUserList(likeDtoList);
            // 存储整个对象
            allTalkVoList.add(allTalkVo);
        }
        // 排序
        List<AllTalkVo> sortedAllTalkVoList = allTalkVoList.stream()
                .sorted(Comparator.comparingInt((AllTalkVo item) -> item.getTalk().getId()).reversed())
                .collect(Collectors.toList());
        return sortedAllTalkVoList;
    }

    /**
     * 保存说说用户
     *
     * @param talkUser
     * @return
     */
    public Integer saveUserTalk(TalkUser talkUser) {
        talkUserMapper.insert(talkUser);
        return talkUser.getId();
    }

    /**
     * 上传说说用户头像
     *
     * @param multipartFile
     * @return
     */
    public String fileUpload(MultipartFile multipartFile) {
        try {
            // 创建minio客户端
            MinioClient minioClient = minIOConfig.buildMinioClient();
            // 判断桶是否存在
            boolean isBucket = minioClient.bucketExists(BucketExistsArgs
                    .builder()
                    .bucket(minIOConfigProperties.getBucket()).build());
            if (!isBucket) {
                // 不存在创建一个桶
                minioClient.makeBucket(MakeBucketArgs.builder().bucket(minIOConfigProperties.getBucket()).build());
            } else {
                // 存在提示用户
                System.out.println("可以开始图片上传了");
            }
            // 存在
            // 构建图片路径 业务+日期格式+图片名称
            String date = DateUtil.format(new Date(), "yyyyMMdd");
            // 唯一id作为图片路径
            String uuid = UUID.randomUUID().toString().replace("-", "");
            // 组合＋业务
            String fileName = "admin-talkuser-avatar" + "/" + date + "/" + uuid + multipartFile.getOriginalFilename();
            // 开始构建参数
            PutObjectArgs putObjectArgs = PutObjectArgs
                    .builder()
                    .bucket(minIOConfigProperties.getBucket())
                    .stream(multipartFile.getInputStream(), multipartFile.getSize(), -1)
                    .object(fileName)
                    .build();
            // 上传至minio客户端
            minioClient.putObject(putObjectArgs);
            // 将路径返回
            return minIOConfigProperties.getReadPath() + "/" + minIOConfigProperties.getBucket() + "/" + fileName;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }

    /**
     * 用户点赞
     *
     * @param id
     * @param status
     * @param talkId
     */
    public void updateLike(Integer id, Integer status, Integer talkId) {
        // 查询该用户的信息
        LambdaQueryWrapper<TalkUser> talkUserLambdaQueryWrapper = new LambdaQueryWrapper<>();
        talkUserLambdaQueryWrapper.eq(TalkUser::getId, id);
        TalkUser talkUser = talkUserMapper.selectOne(talkUserLambdaQueryWrapper);
        if (talkUser == null) {
            throw new BlogException("点赞失败");
        }

        // 查询说说表
        LambdaQueryWrapper<Talk> talkLambdaQueryWrapper = new LambdaQueryWrapper<>();
        talkLambdaQueryWrapper.eq(Talk::getId, talkId);
        Talk talk = talkMapper.selectOne(talkLambdaQueryWrapper);

        // 将状态处理
        Boolean isLiked = false;
        isLiked = status == 1 ? true : false;
        // 将数据存储
        LikeDto likeDto = new LikeDto();
        likeDto.setUrl(talkUser.getAvatar());
        // 开始点赞
        // 将当前的说说点赞信息清除
        Object o = redisTemplate.opsForHash().get("talk" + talkId, id);
        if (o != null) {
            redisTemplate.opsForHash().delete("talk" + talkId, id);
        }
        likeDto.setIsLiked(isLiked);
        // 点赞
        redisTemplate.opsForHash().put("talk" + talkId, id, JSONUtil.toJsonStr(likeDto));
        // 将数量加减
        if (isLiked) {
            // 加1
            talk.setLikeCount(talk.getLikeCount() + 1);
        } else {
            talk.setLikeCount(talk.getLikeCount() - 1);
        }
        // 修改数据库
        talkMapper.updateById(talk);
    }

    /**
     * 查询用户是否已经点赞过了
     *
     * @param id
     * @param talkId
     * @return
     */
    public Integer getIsLike(Integer id, Integer talkId) {
        Object o = redisTemplate.opsForHash().get("talk" + talkId, id);
        if (o == null) {
            return 1;
        }
        // 转换对象
        LikeDto bean = JSONUtil.toBean(o.toString(), LikeDto.class);
        if (!bean.getIsLiked()) {
            return 1;
        }
        return 0;
    }


    /**
     * 评论
     *
     *
     * @param id
     * @param talkId
     * @param remork
     */
    public void comment(Integer id, Integer talkId, String remork) {
        TalkComment talkComment = new TalkComment();
        talkComment.setContent(remork);
        // 向评论表中插入数据
        talkCommentMapper.insert(talkComment);

        // 向用户评论表中插入数据
        UserCommentRelation userCommentRelation = new UserCommentRelation();
        userCommentRelation.setCommentId(talkComment.getId());
        userCommentRelation.setUserId(id);
        userCommentRelationMapper.insert(userCommentRelation);

        // 向评论说说表中插入数据
        TalkCommentRelation talkCommentRelation = new TalkCommentRelation();
        talkCommentRelation.setCommentId(talkComment.getId());
        talkCommentRelation.setTalkId(talkId);
        talkCommentRelationMapper.insert(talkCommentRelation);
    }
}
